using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace EntityKit.Runtime
{
    /// <summary>
    /// 实体管理器增删改查
    /// </summary>
    public partial class EntityManager
    {
        /// <summary>
        /// 添加实体到管理系统
        /// </summary>
        public static void AddEntity(IEntity entity, bool isInit = true)
        {
            if (entity == null || string.IsNullOrEmpty(entity.EntityID) || mIdToEntity.ContainsKey(entity.EntityID))
                throw new Exception($"实体ID不能为空或者重复，请检查EntityID:{entity?.EntityID}");

            var entityType = entity.GetType();
            if (!mTypeToEntities.ContainsKey(entityType))
                mTypeToEntities[entityType] = new List<IEntity>();

            mTypeToEntities[entityType].Add(entity);
            mIdToEntity[entity.EntityID] = entity;
            if (isInit)
                entity.OnInit();
        }

        /// <summary>
        /// 删除实体
        /// </summary>
        public static bool ReleaseEntity(IEntity entity)
        {
            if (!CanReleaseEntity(entity)) return false;
            if (entity.IsInit)
                entity.OnRelease();
            var typeRemoved = mTypeToEntities.Remove(entity.GetType());
            var idRemoved = mIdToEntity.Remove(entity.EntityID);
            return typeRemoved && idRemoved;
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        public static IEntity GetEntity(string entityID)
        {
            return mIdToEntity.GetValueOrDefault(entityID);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        public static T GetEntity<T>(string entityID) where T : class, IEntity
        {
            return mIdToEntity.GetValueOrDefault(entityID) as T;
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        public static IEntity GetEntity(Type type)
        {
            // 首先尝试直接查找精确匹配的类型
            if (mTypeToEntities.TryGetValue(type, out var entities) && entities.Count > 0)
            {
                return entities[0];
            }
            
            foreach (var entityType in mTypeToEntities.Keys.Where(entityType => type.IsAssignableFrom(entityType)))
            {
                if (mTypeToEntities.TryGetValue(entityType, out var derivedEntities) && derivedEntities.Count > 0)
                {
                    return derivedEntities[0];
                }
            }

            return null;
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        public static T GetEntity<T>() where T : class, IEntity
        {
            return GetEntity(typeof(T)) as T;
        }

        /// <summary>
        /// 获取同类型的一组实体
        /// </summary>
        public static List<IEntity> GetEntities(Type type)
        {
            var result = new List<IEntity>();
            
            // 首先查找精确匹配的类型
            if (mTypeToEntities.TryGetValue(type, out var entities))
            {
                result.AddRange(entities);
            }
            
            // 然后查找派生类型
            foreach (var entityType in mTypeToEntities.Keys)
            {
                if (type.IsAssignableFrom(entityType))
                {
                    // 跳过已经处理过的精确匹配类型
                    if (entityType == type) continue;
                    
                    if (mTypeToEntities.TryGetValue(entityType, out var derivedEntities))
                    {
                        result.AddRange(derivedEntities);
                    }
                }
            }
            
            return result;
        }

        /// <summary>
        /// 获取同类型一组实体
        /// </summary>
        public static List<T> GetEntities<T>() where T : class, IEntity
        {
            return GetEntities(typeof(T)).Cast<T>().ToList();
        }

        /// <summary>
        /// 获的系统所有注册的实体
        /// </summary>
        /// <returns></returns>
        public static List<IEntity> GetAllEntities()
        {
            var result = new List<IEntity>();
            foreach (var entityList in mTypeToEntities.Values)
            {
                result.AddRange(entityList);
            }

            return result;
        }


        private static bool CanReleaseEntity(IEntity entity)
        {
            if (entity == null || string.IsNullOrEmpty(entity.EntityID) || !mIdToEntity.ContainsKey(entity.EntityID))
                return false;
            var type = entity.GetType();
            if (!mTypeToEntities.TryGetValue(type, out var entities))
                return false;
            if (!entities.Contains(entity)) return false;
            if (entities.Count == 0)
                mTypeToEntities.Remove(type);
            return mIdToEntity.ContainsKey(entity.EntityID);
        }
    }
}